#include "mythread.h"
#include "./plugIn/serialport.h"
#include <iostream>
using namespace std;



MyThread::MyThread(QObject *parent) : QObject(parent)
{
}

MyThread::~MyThread()
{
}

//开启蓝牙通信
void MyThread::devPortInfo(QString Info,double time)
{
    QString csv_file_name = QDir::currentPath()+"/"+QDateTime::currentDateTime().toString("yyyyMMddHHmmss")+"_"+Info+".csv";
    QFile *csv_file = new QFile(csv_file_name);
    if(!csv_file->open(QIODevice::ReadWrite | QIODevice::Text)){
            qDebug() << "open csv file failed";
            return;
    }
    if(!csv_file->exists()){
         qDebug() << " csv file not exists";
     }
    QTextStream* input_file = new QTextStream(csv_file);
    connect(this,&MyThread::emitCsvFileClose,this,[=](){csv_file->close();delete csv_file;});

    QTime* TIME = new QTime;
    obtainedTimeX(TIME,true);
    InitCSerialPort(Info,time,input_file,TIME);


//    writeCapacitanceData();   //写入电容数值
//    producingModBusData();    //单地址读取压力值

}


void MyThread::InitCSerialPort(QString Info,double time,QTextStream* input_file,QTime* currentTime){
   CSerialPort *cs = new CSerialPort;
   if(!cs->isOpenPort()){
        while(!cs->InitPort(Info.toLatin1().data())){
            Sleep(1);
//            qDebug()<<Info<<"串口未打开";
        }

        cs->OpenListenThread();
        string temp_to_string;
        QString temp_to_qstring;
        bool type = true;
        while(type){
        char buf ;
        cs->ReadChar(buf);
        std::string str(1,buf);
            if(!str.empty()){
                    if(buf =='\n'){
                       temp_to_qstring = QString::fromStdString(temp_to_string);
                       if(temp_to_qstring.size()>60){
                           qApp->processEvents(); //开启事件循环
//                           currentTime->elapsed()/1000;
//                           qDebug()<<"temp_to_qstring:"<<temp_to_qstring;
//                           qDebug()<<"temp_to_qstring:"<<temp_to_qstring<<Info<<"timeX:"<<currentTime->elapsed()/1000.00<<"time:"<<time;
                        dataProcessor(temp_to_qstring,input_file,currentTime->elapsed()/1000.00);
                       }
                       temp_to_qstring.clear();
                       temp_to_string.clear();
                    }else if(buf =='\r'){}else{
                      temp_to_string.append(str);
                    }
            }

            if(time<currentTime->elapsed()/1000.00){
                qDebug()<<Info<<"串口关闭";
                cs->CloseListenTread();
                cs->ClosePort();
                delete cs;

                emit emitCsvFileClose();

                obtainedTimeX(currentTime,false);
                type = false;
                delete input_file;
                delete currentTime;
            }
        }
   }
}

void MyThread::dataProcessor(QString data,QTextStream* input_file,double time){
    QList<int> effective_pressure_data,effective_capacitance_data;
    QList<QString> data_toStringList =  data.split(",");
    for(int i = 0 ; i < data_toStringList.size();i++){
        if(i<9){
            effective_capacitance_data.append(data_toStringList.at(i).toInt());
        }else{
            effective_pressure_data.append(data_toStringList.at(i).toInt());
        }
    }
    if(effective_pressure_data.size()==9&&effective_capacitance_data.size()==9){
//    qDebug()<<"effective_capacitance_data:"<<effective_capacitance_data;
//    qDebug()<<"effective_pressure_data:"<<effective_pressure_data;
//    emit emitCapacitanceData(effective_capacitance_data);//通过modbus将电容数据传给主机
//    emit emitStandardPressure();//通过modbus读取40035寄存器位置数据

        save_csv_file(effective_pressure_data,effective_capacitance_data,input_file,time);//csv与压力数据中间处理函数
        heatMapData(effective_pressure_data);//热力图中间处理函数
    }
    data_toStringList.clear();
    effective_pressure_data.clear();
    effective_capacitance_data.clear();
}

void MyThread::obtainedTimeX(QTime* time,bool time_type){

    if(time_type){
        time->start();
    }else{
        time->restart();
    }
}

void MyThread::save_csv_file(QList<int> nine_pressure_data,QList<int> effective_capacitance_data,QTextStream* input_file,double timeX)
{
//    qDebug()<<"nine_pressure_data:"<<nine_pressure_data;
    emit emitSendData(nine_pressure_data,timeX);//最终发送
    for(int i = 0 ; i < 9 ; ++i){
        *input_file<<nine_pressure_data.at(i)<<",";
    }
    for(int i = 0 ; i < 9 ; ++i){
        i==8? *input_file<<effective_capacitance_data.at(i)<<","<<timeX<<"\n":*input_file<<effective_capacitance_data.at(i)<<",";
    }
    effective_capacitance_data.clear();
    nine_pressure_data.clear();
}

void MyThread::heatMapData(QList<int> nine_pressure_data){
    //    qDebug()<<"九个点压力值："<<nine_pressure_data;
        int nine_pressure_data_list_size = nine_pressure_data.length();
        QList<int> nine_pressure_data_temp;
        QList<int> nine_pressure_data_list_original_location;  //排序后角标的位置
        for(int i = 0; i < nine_pressure_data_list_size;i++){
            nine_pressure_data_temp<<0;
            nine_pressure_data_list_original_location<<0;
            nine_pressure_data_temp[i] = nine_pressure_data[i];  //复制原数组
        }
    //    qDebug()<<"复制后的数组："<<nine_pressure_data_temp;  // (3000, 1000, 3000, 1500, 1500, 1500, 1500, 1500, 1500)
         qSort(nine_pressure_data_temp.begin(),nine_pressure_data_temp.end(),qGreater<int>());
    //    qDebug()<<"排序后的数组："<<nine_pressure_data_temp;  // (3000, 3000, 1500, 1500, 1500, 1500, 1500, 1500, 1000)
        int i = 0,temp_i = 0 ;
        while(i<9){
            temp_i = i ;
            for (int j = 0; j < nine_pressure_data_list_size; j++) {
                if(i!=9){
                    if (nine_pressure_data_temp[i] == nine_pressure_data[j]&&nine_pressure_data_temp[i]!=0) {
                        nine_pressure_data_list_original_location[i] = j;
                        ++i;
                        }else if(nine_pressure_data_temp[i] ==0 ){
                            nine_pressure_data_list_original_location[i] = 99;
                        }
                      }
            }
            if(temp_i==i){
                ++i;
             }
        }
        //    qDebug()<<"排序索引："<<nine_pressure_data_list_original_location;  // (2, 2, 8, 8, 8, 8, 8, 8, 1)
        emit emitHeatMap(nine_pressure_data,nine_pressure_data_list_original_location,nine_pressure_data_temp);//最终发送
}

void MyThread::writeCapacitanceData(){
    QString IP_address = "127.0.0.1";
    int Port = 502;
    QModbusTcpClient *My_client = new QModbusTcpClient();
    My_client->setConnectionParameter(QModbusDevice::NetworkAddressParameter,IP_address);
    My_client->setConnectionParameter(QModbusDevice::NetworkPortParameter,Port);
    My_client->connectDevice();//连接设备
    connect(this,&MyThread::emitCapacitanceData,this,[=](QList<int> capacitance_data){
        QModbusDataUnit writeData(QModbusDataUnit::HoldingRegisters, 2, 30);
        for(int i = 0 ; i < 9 ; i ++){
            writeData.setValue(i, capacitance_data.at(i)); //这里需要写值
        }
        My_client->sendWriteRequest(writeData, 1);
        capacitance_data.clear();
    });
}


void MyThread::producingModBusData(){  
    QString IP_address = "127.0.0.1";
    int Port = 502;
    QModbusTcpClient *My_client = new QModbusTcpClient();
    My_client->setConnectionParameter(QModbusDevice::NetworkAddressParameter,IP_address);
    My_client->setConnectionParameter(QModbusDevice::NetworkPortParameter,Port);
    My_client->connectDevice();//连接设备
    QModbusDataUnit data(QModbusDataUnit::HoldingRegisters, 34, 1);//读取40035寄存器位置数据

    connect(this,&MyThread::emitStandardPressure,this,[=](){
        auto reply =  My_client->sendReadRequest(data, 0x1);
        if (!reply->isFinished())
        {
         connect(reply, &QModbusReply::finished, this, [=](){
             auto reply1 = qobject_cast<QModbusReply*>(sender());
             const QModbusDataUnit responseData = reply1->result();
             qDebug()<<"读到数据为：" << responseData.values();
         });
        }else{
         reply->deleteLater();
        }
    });
}

////modbus单点采集以及多点采集模块

void MyThread::recviceIP(QString IP,bool Type,QString token,QString save_floder)
{
    IP_address = IP;
    TYPE = Type;
    TOKEN = token;
    SaveFloder = save_floder;
    qDebug()<<TOKEN;
    qDebug()<<SaveFloder;
    qDebug()<<"1.TYPE:"<<TYPE<<"thread:"<<this->thread();
    modbusStarting();
}


bool MyThread::modbusStarting()
{
    qDebug()<<"2.开始modbusTcp连接。"<<"thread:"<<this->thread();
    qDebug()<<"3.IP address："<<IP_address<<"thread:"<<this->thread();

    int Port = 502;
    My_client = new QModbusTcpClient();
    if (My_client->state() != QModbusDevice::ConnectedState) {       //判断当前连接状态是否为断开状态

        //配置modbus tcp的连接参数 IP + Port   modbus协议的端口号为502
        My_client->setConnectionParameter(QModbusDevice::NetworkAddressParameter,IP_address);
        My_client->setConnectionParameter(QModbusDevice::NetworkPortParameter,Port);
        if (My_client->connectDevice()) {
            if(My_client->state() == QModbusDevice::ConnectingState){
//                qDebug()<< "4.正在连接到modbs设备"<<"thread:"<<this->thread();
                           }
            if(My_client->state() == QModbusDevice::ConnectedState){
                qDebug()<< "4.成功连接到modbs设备";
                connect(My_client, &QModbusClient::stateChanged,this, &MyThread::btnHoldingRegisters);
            }
            return true;
        }
        else {
            qDebug()<< "连接modbus设备失败";
//            My_client = nullptr;
            My_client->deleteLater();

            return false;

        }
    }

    else {
        qDebug()<< "连接断开";
        My_client->disconnectDevice();
//        My_client = nullptr;
        My_client->deleteLater();
        return false;
    }
}


//读保持寄存器
void MyThread::btnHoldingRegisters()
{
    if(!TYPE){//type = false

        //从地址0开始读取32个保持寄存器的值
        QModbusDataUnit data(QModbusDataUnit::HoldingRegisters, 2, 30);
        auto reply =  My_client->sendReadRequest(data, 0x1);
        if (nullptr == reply)
        {
            qDebug() << "单点发送请求数据失败: " << My_client->errorString()<<"thread:"<<this->thread();
            delete reply;
            My_client=nullptr;
            My_client->deleteLater();
            emit errorClient();

        }else{
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this, [=](){
                    onReadReady();
                    if(errorTYPE){//如果errorTYPE为true
                        delete reply;
                        My_client = nullptr;
                        My_client->deleteLater();
                        emit errorType();
                    }else{
                    sendDATA();
                    delete reply;
                    My_client = nullptr;
                    My_client->deleteLater();}
                });
            }
        }
    }else{//type = true

        //从地址99开始读取271个保持寄存器的值
        QModbusDataUnit data(QModbusDataUnit::HoldingRegisters, 99,100);
        QModbusDataUnit data1(QModbusDataUnit::HoldingRegisters, 199,100);
        QModbusDataUnit data2(QModbusDataUnit::HoldingRegisters, 299,71);

        auto reply =  My_client->sendReadRequest(data, 0x1);
        auto reply1 = My_client->sendReadRequest(data1, 0x1);
        auto reply2 = My_client->sendReadRequest(data2, 0x1);
        if (nullptr == reply||nullptr == reply1||nullptr == reply2||My_client->state()== QModbusDevice::UnconnectedState)
        {
            qDebug() << "多点发送请求数据失败: " << My_client->errorString()<<endl<<"My_client->state():"<<My_client->state();
            delete reply;
            delete reply1;
            delete reply2;
            My_client->deleteLater();

            emit errorClient();
        }else{
            if (!reply->isFinished())
            {
                connect(reply, &QModbusReply::finished, this,[=](){
                    if(My_client->state()!= QModbusDevice::UnconnectedState){
                    onReadReady();
                    delete reply;
                     }
                });

            }

            if (!reply1->isFinished())
            {
                connect(reply1, &QModbusReply::finished, this,[=](){
                    if(My_client->state()!= QModbusDevice::UnconnectedState){
                    onReadReady();
                    delete reply1;
                    }
                });
            }
            if (!reply2->isFinished())
            {
                connect(reply2, &QModbusReply::finished, this,[=](){

                if(My_client->state()!= QModbusDevice::UnconnectedState){
                    onReadReady();
                    if(errorTYPE){//如果errorTYPE为true
                        delete reply2;
                        My_client = nullptr;
                        My_client->deleteLater();
                        emit errorType();
                    }else{

                        delete reply2;
                        btnHoldingRegisters_2();//进入写寄存器
                    }
                 }
                });
            }
        }

    }

}


void MyThread::onReadReady()
{
    auto reply = qobject_cast<QModbusReply*>(sender());
    if (nullptr == reply)
    {
        return;
    }
    //判断是否出错
    if (reply->error() == QModbusDevice::NoError)
    {
        //读取响应数据
        const QModbusDataUnit responseData = reply->result();
        for(int i = 0;i<responseData.values().size();i++){
             DATA.append(responseData.values().at(i)/100.00);
        }
        qDebug() << "5.通过"<<My_client->thread()<<"读到数据为：" << responseData.values();
    }else if (reply->error() == QModbusDevice::ProtocolError){
        qDebug() << "Read response Protocol error: " << reply->errorString();
        errorTYPE = true;
    }else{
        qDebug() << "Read response Error: " << reply->errorString();
    }
    //删除reply
    reply->deleteLater();
}


//写保持寄存器
void MyThread::btnHoldingRegisters_2()
{
    qDebug()<<"ture为多，false为单"<<TYPE<<endl<<"DATA长度："<<DATA.size()<<endl<<"DATA.at(0):"<<DATA.at(0);
    float number = 0.01;//寄存器地址99的标识符为1
    if(TYPE&&DATA.at(0)==number){
        QModbusDataUnit writeData(QModbusDataUnit::HoldingRegisters, 99, 1);
        writeData.setValue(0, 0);
        qDebug() << "6.read datas: " << writeData.values();
        QModbusReply* reply = My_client->sendWriteRequest(writeData, 1);
        if (reply)
        {
            if (!reply->isFinished())
            {   //接收响应信息
                connect(reply, &QModbusReply::finished, this, [this, reply](){
                    if (reply->error() == QModbusDevice::ProtocolError)
                    {   //接收到的响应信息是协议错误
                        qDebug() << "写入数据错误：" << reply->errorString();
                        My_client = nullptr;
                        My_client->deleteLater();
                    }else if (reply->error() != QModbusDevice::NoError){
                        //接收到的响应消息是其它错误
                        qDebug() << "写入数据错误： " << reply->errorString();
                        My_client = nullptr;
                        My_client->deleteLater();
                    }else{
                        //接收到的消息没有错误 一般没有必要解析响应消息
                        const QModbusDataUnit data = reply->result();
                        qDebug() << "7.消息数据个数：" << data.valueCount() << " :" << data.values();
                        sendDATA();
                        My_client = nullptr;
                        My_client->deleteLater();
                    }
                    reply->deleteLater();
                });
            }else{
                //发送没有响应数据
                //broadcast replies return immediately
                reply->deleteLater();
            }
        }else{
            qDebug() << "sendWriteRequest Error: " << reply->errorString();
        }
    }else if(TYPE&&DATA.length()!=271){
        QTest::qSleep(5000);
        qDebug()<<"The last read needs to be reread."<<endl;
        DATA.clear();
        DATA.shrink_to_fit();
        btnHoldingRegisters();//重新再来 进入读寄存器
    }else{
        QTest::qSleep(5000);
        qDebug()<<"The last read was not completed and needs to be reread."<<endl;
        DATA.clear();
        DATA.shrink_to_fit();
        btnHoldingRegisters();//重新再来 进入读寄存器
    }
}

//生成csv文件并发送data
void MyThread::sendDATA()
{


    if(DATA.back()>0){
        QDateTime current_date_time =QDateTime::currentDateTime();
        QString current_date =current_date_time.toString("yyyyMMddHHmmss");
        QString Name;
        TYPE?Name = "MultiPoint":Name = "SinglePoint";
        modFile= new QFile(SaveFloder+"\\"+Name+"_"+current_date+".csv");
        if(modFile->open(QIODevice::WriteOnly|QIODevice::Text)){
              QTextStream out(&*modFile);
//              QTextCodec* cod=QTextCodec::codecForLocale();
              QString o = "Ω";
              out<<"Pressure(kg),Resistance(k"+o.toUtf8()+")\n";
              if(TYPE==false){
                  for(int i=0;i<DATA.size();i++){
                     if(i%2!=0){
                         out<<DATA[i]<<"\n";
                     }else{
                         out<<DATA[i]<<",";
                     }
                  }
              }else{
                  DATA.remove(0);
                  for(int i=0;i<DATA.size();i++){
                     if(i%2!=0){
                         out<<DATA[i]<<"\n";
                     }else{
                         out<<DATA[i]<<",";
                     }
                  }
              }
               modFile->close();
               out.flush();
//               DATA.clear();
//               DATA.shrink_to_fit();
               HTTPWork();


           }else{
                qDebug()<<"文件无法读写。";
           }
    }
    else{
        emit errorData();
    }
}


void MyThread::HTTPWork(){
     //文件HTTP上传
    m_manager = new QNetworkAccessManager();
//    m_manager->setNetworkAccessible(QNetworkAccessManager::Accessible);
    QUrl url(baseUrl + uploadModFileApi);
    qDebug()<<"...............................................................url:"<<url;
    QNetworkRequest request(url);
    qDebug()<<"上传zip文件时，提交token字符串："<<TOKEN;
    request.setRawHeader("Authorization",TOKEN.toUtf8());

    QHttpPart filePart;

    fileInfo = new QFileInfo(modFile->fileName());
     qDebug()<<"modFile.fileName:"<<fileInfo->fileName();
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(QString("form-data; name=\"file\";filename=\"%1\"")
                                                                           .arg(fileInfo->fileName())));
    qDebug()<<"1";
    modFile = new QFile(fileInfo->absoluteFilePath());
    modFile->open(QIODevice::ReadOnly);
    filePart.setBodyDevice(modFile);
    qDebug()<<"2";
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    multiPart->append(filePart);
    modFile->setParent(multiPart);
    qDebug()<<"3";
    REPLY = m_manager->post(request, multiPart);
    connect(REPLY,&QNetworkReply::readyRead,this,&MyThread::uploadReply);
    QEventLoop eventLoop;//事件计时
    connect(m_manager,SIGNAL(finished(QNetworkReply*)),&eventLoop,SLOT(quit()));
    eventLoop.exec();

    m_manager->deleteLater();
    m_manager = nullptr;

    modFile->close();
    modFile = nullptr;
    modFile->deleteLater();

}



void MyThread::uploadReply()//网络请求回复管理中的上传回复
    {
        qDebug()<<"网路请求的上传回复reply";
        QByteArray ba;
        while (!REPLY->atEnd())
        {
            ba = REPLY->readAll();
        }
        QJsonDocument document = QJsonDocument::fromJson(ba);
        QJsonObject replyObject = document.object();
        qDebug()<<"replyObject的值："<<replyObject;
        int status = replyObject.value("code").toInt();//更新
        qDebug()<<"replyObject中的code的值："<<status;

        if(status == 20000)
        {
//           int serverFile = replyObject.value("data").toObject().value("id").toInt();  //更新
//            qDebug()<<"上传文件的id(serverFile的值)为："<<serverFile;

            qDebug()<<endl<<"Next Reading...";
            for(int i=  0; i<3;i++){
                qDebug()<<"Preparing:"<<i+1;
                QTest::qSleep(1000);
            }
            emit ChartMOd(DATA,fileInfo->fileName());
        } else {
            QString msg = replyObject.value("message").toString();
            qDebug()<< status;
            qDebug()<< msg;
            QString info = "上传失败:" + QString::number(status) + msg;
            qDebug()<< info;
            emit errorUpload(info);
            REPLY->deleteLater();
            REPLY = nullptr;
            return;
        }
        REPLY->deleteLater();
        REPLY = nullptr;
}







